home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Collections: New Zealand Amiga Users Group
/
New Zealand Amiga Users Group Newsdisk v27 (1989-12)(NZAmigaUG).zip
/
New Zealand Amiga Users Group Newsdisk v27 (1989-12)(NZAmigaUG).adf
/
Cal
/
cal.asm
< prev
next >
Wrap
Assembly Source File
|
1993-12-03
|
39KB
|
1,335 lines
; Version 1.0
; Cal.asm
;
; by Steve Martin
;
; Hope you understand this mess.
;
; Copyright: People can do what they want with this progrm except
; to sell it, also I am not responsible for anything.
;
nolist
incdir 'vd0:include/'
include 'exec/exec_lib.i'
;include 'exec/types.i'
;include 'exec/memory.i'
;include 'intuition/intuition.i'
include "libraries/dos_lib.i"
xref _LVOOpenLibrary
xref _LVOCloseLibrary
xref _LVOInput
xref _LVOOutput
xref _LVORead
xref _LVOWrite
; list
ExecBase equ 4
calexec MACRO
move.l ExecBase,a6
jsr _LVO\1(a6)
ENDM
caldos MACRO
move.l DosBase,a6
jsr _LVO\1(a6)
ENDM
; A0 holds the address of the command parameters
; D0 holds the length of the command parameters
; command string ends with $0A
start move.l a0,ipadd store address of command line
move.w d0,iplen store length of command line
getDOS lea.l DosName,a1 library to open
moveq #0,d0 library version (do not care)
calexec OpenLibrary open library
tst.l d0 test if succesful (0 = NG)
bne.s DosOK
moveq #20,d0 return code to tell user system problem
rts return to operating system
DosOK move.l d0,DosBase Save DOS base pointer
caldos Input find standard input
move.l D0,stdin save
caldos Output find standard output
move.l D0,stdout save
;*************************************************************************
iptype bsr getchar get first character form input
cmpi.b #"$",d1 is the number enter in HEX
bne.s ipt2
moveq #0,d1
bra Selip
ipt2 cmpi.b #"@",d1 is the number enter in OCT
bne.s ipt3
moveq #1,d1
bra Selip
ipt3 cmpi.b #"%",d1 is the number enter in binary
bne ipt4
moveq #2,d1
bra Selip
ipt4 cmpi.b #"-",d1 is the number negative
bne others
seq neg set neg flag
moveq #3,d1
bra Selip
others subi.b #$30,d1 is input < 0
bmi error1 yes, error
cmpi.b #9,d1 is the character a decimal number
bgt error1
sub.l #1,ipadd move pointer back a character
add.w #1,iplen incrememt length not read
moveq #3,d1 d1 = decimal input
Selip lsl #2,d1 cal index for jump table
lea Selipt,a0 get address of jump table
move.l 0(a0,d1.w),a0 get address of input routine
jsr (a0)
bcs error1
bsr opert if operator, action it
bmi result
bcc.s nip get net input type
bra operr if operator err
nip bra iptype check input type
Selipt dc.l HEXip,OCTip,BINip,DECip
;*************************************************************************
result clr d0
move.b func,d0 get function pointer
subq #1,d0
lsl #2,d0 cal index for jump table
lea selfunc,a0 get address of jump table
move.l 0(a0,d0.w),a0 get address of func routine
jsr (a0)
tst.b err
bne error1
bsr HtoA
bsr OtoA
bsr BtoA
bsr DtoA
lea BuffHS,a3
bsr nextlin
lea BuffOS,a3
bsr nextlin
lea BuffBS,a3
bsr nextlin
lea BuffDS,a3
bsr nextlin
lea blank,a3
bsr nextlin
bra quit
selfunc dc.l add,sub,mult,div
;*************************************************************************
quit move.l DosBase,a1 Close DOS library
calexec CloseLibrary
moveq #0,d0 Zero return code
rts return to Operating System
;*************************************************************************
opert move.b func,d2
bne.s opequal if func <> 0 then equal is expected
add? cmpi.b #"+",d1 is operator +,if so func = 1
bne.s sub?
move.b #1,func
bra nextval
sub? cmpi.b #"-",d1 is operator -,if so func = 2
bne.s mult?
move.b #2,func
bra nextval
mult? cmpi.b #"*",d1 is operator *,if so func = 3
bne.s div?
move.b #3,func
bra nextval
div? cmpi.b #"/",d1 is operator /,if so func = 4
bne.s operr1
move.b #4,func
nextval move.l #4,VarPtr Point to next variable
rts
operr1 ori #%1,ccr set carry if error only
andi #%1,ccr
rts
opequal cmpi.b #"=",d1 is operator =, if so get result
beq opeq
cmpi.b #$0a,d1 is operator a return, if so get result
beq opeq
bra operr1 if not, error
opeq moveq #-1,d1
rts
;*************************************************************************
operr lea oInfo,a3 get start address of operator error info
bsr nextlin output message
;*************************************************************************
error1 lea Info,a3 get start address of information
bsr nextlin output message
bra quit
;*************************************************************************
nextlin move.l a3,d2 move start address to buffer (d2) of write
moveq #0,d3 clear length input (d3) of write
mesloop move.b (a3)+,d1
beq.s wrend if null (0) all info has been output so end
addq #1,d3 add 1 to length
cmpi.b #$0a,d1 check to see if at end of line
bne.s mesloop if not get next character
wrinfo move.l stdout,d1 stdout file handle
caldos Write Output line to standard output (screen)
bra.s nextlin Output next line of info
wrend rts
;*************************************************************************
getchar move.l ipadd,a0 get address of command line
move.w iplen,d0 get length of command line
next_c moveq #0,d1 clear d1
move.b (a0)+,d1 move next character to d1 and
;increment address pointer
subq #1,d0 decrement length counter
cmpi.b #$20,d1 is it a space
beq.s next_c get next character
move.l a0,ipadd save current pionter to input address
move.w d0,iplen save length not read
rts
;*************************************************************************
oper cmpi.b #"+",d1 is the character an operator
beq.s op1
cmpi.b #"-",d1
beq.s op1
cmpi.b #"/",d1
beq.s op1
cmpi.b #"*",d1
beq.s op1
cmpi.b #"=",d1
beq.s op1
cmpi.b #$0a,d1
beq.s op1
bra.s opend
op1 ori #1,ccr set carry bit if an operator
opend rts
;******************************************************************
;* *
;* Input handling Routines *
;* *
;******************************************************************
;******************************************************************
;* *
;* HEX Input handling Routine *
;* *
;******************************************************************
HEXip bsr getchar
bsr oper is the character an operator
bcc.s Hno_op if carry clear, character not an operator
andi #0,ccr clear carry before returning
rts
Hno_op cmpi.b #"0",d1 if input character is less than an ascii 0
blt Herror then in put is in error
cmpi.b #$3a,d1 is in put character between ,including 0 - 9
blt.s HEXnum yes, do not subtract $37 from ascii value
letter cmpi.b #"a",d1 is input greater than a
blt.s letter2 is character a capital letter?
andi.b #%11011111,d1 no, so convert to a capital
letter2 cmpi.b #"A",d1 is input between and including A and F
blt Herror
cmpi.b #"F",d1
bgt Herror no, HEX number in error
subi.b #$7,d1 yes, convert to a value between and including
; 3A and 3F
HEXnum subi.b #$30,d1 convert input to a value between 0 and F
lea VarPtr,a0
move.l 0(a0),d0 move VarPtr to d0
move.l 4(a0,d0.w),d2 get current variable
moveq #0,d3 clear counter register
hshift asl.l #1,d2 shift left 4 bit places
bcs.s Herror if carry set number intered was to large
addq #1,d3 inc counter
cmpi #4,d3 shifted four places?
bne.s hshift no, repeat
or.l d1,d2 yes, add input character to variable
move.l d2,4(a0,d0.w) save current variable
bra.s HEXip get next character
Herror lea hInfo,a3 get start address of operator error info
bsr nextlin output message
ori #1,ccr set carry to indicate an error
rts
;******************************************************************
;* *
;* OCT Input handling Routine *
;* *
;******************************************************************
OCTip bsr getchar
bsr oper is the character an operator
bcc.s Ono_op if carry clear, character not an operator
andi #0,ccr clear carry before returning
rts
Ono_op subi.b #$30,d1 remove ascii offset
blt.s Oerror if input character is less than an ascii 0
;then in put is in error
cmpi.b #7,d1 is in put character between ,including 0 - 7
bgt.s Oerror no, error
OCTnum lea VarPtr,a0
move.l 0(a0),d0 move VarPtr to d0
move.l 4(a0,d0.w),d2 get current variable
moveq #0,d3 clear counter register
Oshift asl.l #1,d2 shift left three bit places
bcs.s Oerror if carry set number intered was to large
addq #1,d3 inc counter
cmpi #3,d3 shifted 3?
bne.s Oshift no, do it again
or.l d1,d2 add input to variable
move.l d2,4(a0,d0.w) save current variable
bra.s OCTip get next character
Oerror lea OInfo,a3 get start address of operator error info
bsr nextlin output message
ori #1,ccr set carry to indicate an error
rts
;******************************************************************
;* *
;* BIN Input handling Routine *
;* *
;******************************************************************
BINip bsr getchar
bsr oper is the character an operator
bcc.s Bno_op carry clear, character not an operator
andi #0,ccr clear carry before returning
rts
Bno_op subi.b #$30,d1 remove ascii offset
blt.s Berror if input character is less than an ascii 0
;then in put is in error
cmpi.b #1,d1 is in put character 0 or 1
bgt.s Berror no, error
BINnum lea VarPtr,a0
move.l 0(a0),d0 move VarPtr to d0
move.l 4(a0,d0.w),d2 get current variable
Bshift asl.l #1,d2 shift left one bit place
bcs.s Berror if carry set number intered was to large
or.l d1,d2 add input to variable
move.l d2,4(a0,d0.w) save current variable
bra.s BINip get next character
Berror lea BInfo,a3 get start address of operator error info
bsr nextlin output message
ori #1,ccr set carry to indicate an error
rts
;******************************************************************
;* *
;* DEC Input handling Routine *
;* *
;******************************************************************
DECip bsr getchar
bsr oper is the character an operator
bcc.s Dno_op carry clear, character not an operator
tst.b neg test neg flag is set
beq.s DECpos if operator is "-" and neg flag clear,return
bsr.s DECneg if neg flaf set, make number negative
DECpos andi #0,ccr clear carry defore returning
rts
DECneg lea VarPtr,a0 if negative
move.l 0(a0),d0 move VarPtr to d0
move.l 4(a0,d0.w),d2 get current variable
neg.l d2 make it negative
move.l d2,4(a0,d0.w) save current variable
clr.b neg clear negative flag
rts
Dno_op subi.b #$30,d1 remove ascii offset
blt.s Derror if input character is less than an ascii 0
;then in put is in error
cmpi.b #9,d1 is in put character between, including 0 or 9
bgt.s Derror no, error
DECnum lea VarPtr,a0
move.l 0(a0),d0 move VarPtr to d0
move.l 4(a0,d0.w),d2 get current variable
move.l d2,d3 mult by 10
asl.l #1,d3 *2
bvs.s Derror if ovrflow input dec number is to large
move.l d3,d4 save * 2 result
asl.l #2,d3 *4, total of *8
bvs.s Derror if ovrflow input dec number is to large
add.l d3,d4 add *2 result to *8 result
bmi.s Derror if becomes neg input dec number is to large
add.l d1,d4 add input to value
move.l d4,4(a0,d0.w) save current variable
bra.s DECip get next character
Derror lea DInfo,a3 get start address of operator error info
bsr nextlin output message
ori #1,ccr clear carry before returning
rts
;******************************************************************
;* *
;* Math Handling Routines *
;* *
;******************************************************************
;******************************************************************
;* *
;* ADD Routine *
;* *
;******************************************************************
add lea VarPtr,a0
lea Total,a1
moveq #0,d1
move.l 0(a0),d0 move VarPtr to d0
move.l 4(a0),d2 move Var1 to d2
move.l 4(a0,d0.w),d3 move Var2 to d3
add.l d3,d2 add variables
svs err if over flow, err = -1
bvc.s addok if add ok, save result and output
lea adderrI,a3 no, output error
bsr nextlin
bra addend
addok move.l d1,(a1) save result
move.l d2,4(a1)
addend rts
;******************************************************************
;* *
;* SUB Routine *
;* *
;******************************************************************
sub lea VarPtr,a0
lea Total,a1
moveq #0,d1
move.l 0(a0),d0 move VarPtr to d0
move.l 4(a0),d2 move Var1 to d2
move.l 4(a0,d0.w),d3 move Var2 to d3
sub.l d3,d2 var1 - var2
svs err if over flow, err = -1
bvc.s subok sub ok, save reult and output
lea suberrI,a3 no, output error message
bsr nextlin
bra subend
subok move.l d1,(a1) save result
move.l d2,4(a1)
subend rts
;******************************************************************
;* *
;* MULT Routine *
;* 32 * 32 = 64 *
;* *
;******************************************************************
mult lea VarPtr,a0
lea Total,a1 a1 points to result storage area
move.l 0(a0),d0 move VarPtr to d0
move.l 4(a0),d1 move Var1 to d1
move.l 4(a0,d0.w),d2 move Var2 to d2
move.l d1,d6 copy var1 to d6
move.l d2,d7 copy var2 to d7
mul32 move.l d1,d3 copy var1 to d3
move.l d1,d4 and into d4
swap d4 swaped form (upper 2 bytes swapped with lower)
move.l d2,d5 copy var2 to d5
swap d5 in swapped form
mulu d2,d1 partial product #1
mulu d4,d2 #2
mulu d5,d3 #3
mulu d5,d4 #4
swap d1 sum1 = pp #2 low +
add d2,d1 pp #1 high
clr.l d5
addx.l d5,d4 propagate carry into pp #4
add d3,d1 sum2 = sum1 + pp #3 low
addx.l d5,d4 propargate carry into pp #4
swap d1 put low product in correct order
clr d2 prepare for sum #3
swap d2
clr d3
swap d3
add.l d3,d2 sum3 = pp #2 low + pp #3 high
add.l d4,d2 sum4 = sum3 + pp #4
;
; The following instructions modify the product if required
;
tst.l d7 val2 negative?
bpl.s CHKd6 no, go check val1
sub.l d6,d2 yes, sub val1 from product
CHKd6 tst.l d6 val1 negative
bpl.s mulend no, finish
sub.l d7,d2 yes, sub val2 from product
mulend move.l d2,(a1) save result, high 32 bits
move.l d1,4(a1) low 32bits
rts
;******************************************************************
;* *
;* DIV Routines *
;* *
;******************************************************************
div lea VarPtr,a0
lea Total,a1 a1 points to result storage error
move.l 0(a0),d0 move VarPtr to d0
move.l 4(a0),d2 move Var1 to d2
move.l 4(a0,d0.w),d1 move Var2 to d1
div0 moveq #0,d6
moveq #0,d7
tst.l d1 is var2 negative or zero
seq err if zero, divid by zero
beq.s dbyz and output message
smi d6 set d6 if var2 is negative
bpl.s div1 positive, test next variable
neg.l d1 make var2 positive
div1 tst.l d2 is var1 negative
smi d7 set d7 if var1 is negative
bpl.s div2 positive, divid var1 by var2
neg.l d2 make var1 positive
div2 eor d6,d7 are signs different
sne.b neg if signs are different result must be neg
cmpi.l #$FFFF,d1 is var2 larger than 16 bits
sls d6 if lower or same set d6 to -1
addi.b #1,d6 calculate jump offset
lsl.l #2,d6 *4 to get address
lea divlen,a3 get address of jump table
move.l 0(a3,d6.w),a3 move address of divid routine to a3
jsr (a3)
divend move.l d2,(a1) quotient
move.l d1,4(a1) remainder
rts
divlen dc.l d32.16,d32.32
dbyz lea dbyzI,a3 output divid by zero message
bsr nextlin
rts
;
; Use this routine if var2 is stored in 16 bits or less
; Uses 68000 divid operand and accounts for over flow when the quotient
; needs 32 bits instead of the standard 16
;
; d2 = dividend
; d1 = divisor
d32.16 moveq #0,d4
divu d1,d2 Has overflow occurred?
bvc.s dformat No, go format result
move.l d2,d3 Yes, copy yo into d3
clr.w d2 clr low word of d2, y1-y0 to y1-0
swap d2 y1-0 to 0-y1
divu d1,d2 div puts r1-q1 into d2
move d2,d4 d3 contains q1
move d3,d2 d1 changes from r1-q1 to r1-y0
divu d1,d2 div puts r0-q0 into d1
;
; Form quotient (D2) and remainder (D1)
;
dformat move.l d2,d1 d1 contains r-q or r0-q0
swap d2 d2 contains q-r or q0-r0
move d4,d2 d2 contains q-0 or q0-q1
swap d2 d2 contains 0-q or q1-q0
clr d1 d1 contains r-0 or r0-0
swap d1 d1 contains 0-r or 0-r0
tst.b neg is result to be negative
beq.s d32.16e no, return
neg.l d2 yes, make neqative
neg.l d1
clr.b neg
d32.16e rts
;
; Use this routine if var2 is stored in 16 bits or less
; Uses a divid algorithm
;
; d2 = dividend
; d1 = divisor
;
d32.32 cmp.l d2,d1 divisor = dividend
bne.s divi1 no, divid out
moveq #1,d3 yes, result = 1
moveq #0,d2 zero remainder
bra.s divout return
divi1 cmp.l d2,d1 dividend > divisor?
bcs.s divi2 yes, result is > 0
moveq #0,d3 else result = 0 + r
bra.s divout return
divi2 moveq #0,d4 initialise iteration count
divi3 addq #1,d4 inc count
asl.l #1,d1 see if d1 goes > 0
bmi.s divi4 it did if now neg
cmp.l d1,d2 d1 > 0
bcc.s divi3 no, try again
divi4 lsr.l #1,d1 readjust divisor
moveq #0,d3 initialise quotient
divi5 sub.l d1,d2 divisor goes in
bmi.s divi6 no
addq #1,d3 else record it
bra.s divi7
divi6 add.l d1,d2 restore dividend
divi7 subq #1,d4 done all bits?
beq.s divout yes
asl.l #1,d3 quotient * 2
asr.l #1,d1 divisor / 2
bra.s divi5 next round
divout move.l d2,d1 move remainder to d1
move.l d3,d2 move quotient to result
tst.b neg should result be neg
beq.s d32.32e no exit
neg.l d2 change sign of result
neg.l d1
clr.b neg
d32.32e rts
;******************************************************************
;* *
;* Output Handling Routines *
;* *
;******************************************************************
;******************************************************************
;* HtoA *
;* Converts variable pointed to by VarPtr to *
;* a HEX ascii string for displaying. *
;******************************************************************
HtoA lea VarPtr,a0
move.l #12,d4 point to result
lea BuffT,a1 get address of tempory buffer
move.l #147,d3 point to end of buffer
GetH move.l 4(a0,d4),d0 get a varible
cmpi.b #12,d4 pointing to result
blt.s GetH0 no, no special trement
cmpi.b #4,func is operation div
beq.s Hdiv yes, output in divid format
GetH0 cmpi #8,d4 remove if leading zeros are to be removed
bne.s GetH1 "
tst.l d0 "
bne.s GetH1 "
subq #4,d4 "
bsr Iequal "
bra.s GetH "
GetH1 bsr HtoAt change variable to ascii in HEX base
tst.b err error in converstion
bne.s HtoAerr output error message
nextH subq #4,d4 point to next variable
bmi.s BTtoBH if negative all variables actioned
beq.s Hoper d4 = 0, then output relavent operator
Hequal cmpi #4,d4 has total been actioned
bhi.s GetH higher, get high 32 bits of result
bsr Iequal d4 = 4, insert "=" sign
bra.s GetH get next variable
Hoper bsr Ifunc branch to insert operator routine
bra GetH get next variable
BTtoBH lea BuffH,a0 a0 points to HEX output buffer
;jsr Rled0 remove leading zeros
jsr BTcopy do not remove leading zeros
rts
Hdiv move.l #9,d5 insert "remainder" into tempory buffer
lea rem,a2 a2 points to remainder
Hdiv1 move.b 0(a2,d5.w),d6 get a letter
move.b d6,0(a1,d3.w) put it into tempory buffer
subq #1,d3 point to next letter
dbf d5,Hdiv1 d5 = 0, then finished
Hdiv2 bsr HtoAt convet to ascii, HEX base
move.b #' ',0(a1,d3.w) add "+" to buffer
subq #1,d3
move.b #'+',0(a1,d3.w)
subq #1,d3
move.b #' ',0(a1,d3.w)
subq #1,d3
subq #4,d4 point to quotient
move.l 4(a0,d4.w),d0 get quotient
bsr HtoAt convert to ascii, HEX base
bra nextH get var2
HtoAerr lea HtoAI,a3 output error message
bsr nextlin
rts
HtoAt moveq #8,d1 do not remove leading zeros
;move to remove leading zeros
HtoAtp move.l d0,d2
andi.l #$0000000F,d2 get lsnibble
addi.l #$30,d2 ascii offset for num
cmpi.l #$39,d2 larger than $39
ble.s HtoAct no do not add $7, yes, add $7
addq.l #$7,d2 ascii offset for alpha
HtoAct move.b d2,0(a1,d3.w) move to tempory buffer
subq #1,d3 point to next buffer place
lsr.l #4,d0 move next byte into LSnibble
subq #1,d1 decrememt counter, remove to delete leading
;zero
smi.b err if negative, an error has occurred
bgt.s HtoAtp if greater convert next byte
rts
;******************************************************************
;* OtoA *
;* Converts variable pointed to by VarPtr to *
;* a OCT ascii string for displaying. *
;******************************************************************
OtoA lea VarPtr,a0
move.l #12,d4 point to result
lea BuffT,a1 get address of tempory buffer
move.l #147,d3 point to end of buffer
GetO move.l 4(a0,d4),d0 get a varible
cmpi.b #12,d4 pointing to result
blt.s GetO0 no, no special treatment
cmpi.b #4,func is operation div
beq.s Odiv yes, output in divid format
GetO0 cmpi #8,d4 remove if leading zeros are to be removed
bne.s GetO1 "
tst.l d0 "
bne.s GetO1 "
subq #4,d4 "
bsr Iequal "
bra.s GetO " "
GetO1 bsr OtoAt change variable to ascii in OCT base
tst.b err error in converstion
bne.s OtoAerr output error message
nextO subq #4,d4 point to next variable
bmi.s BTtoBO if negative all variables actioned
beq.s Ooper d4 = 0, then output relavent operator
Oequal cmpi #4,d4 has total been actioned
bhi.s GetO higher, get high 32 bits of result
bsr Iequal d4 = 4, insert "=" sign
bra.s GetO get next variable
Ooper bsr Ifunc branch to insert operator routine
bra GetO get next variable
BTtoBO lea BuffO,a0 a0 points to OCT output buffer
;jsr Rled0 remove leading zeros
jsr BTcopy do not remove leading zeros
rts
Odiv move.l #9,d5 insert "remainder" into tempory buffer
lea rem,a2 a2 points to remainder
Odiv1 move.b 0(a2,d5.w),d6 get a letter
move.b d6,0(a1,d3.w) put it into tempory buffer
subq #1,d3 point to next letter
dbf d5,Odiv1 d5 = 0, then finished
Odiv2 bsr OtoAt convet to ascii, BIN base
move.b #' ',0(a1,d3.w) if so add + to buffer
subq #1,d3
move.b #'+',0(a1,d3.w)
subq #1,d3
move.b #' ',0(a1,d3.w)
subq #1,d3
subq #4,d4 point to quotient
move.l 4(a0,d4.w),d0 get quotient
bsr OtoAt convert to ascii, OCT base
bra nextO get var2
OtoAerr lea HtoAI,a3 output error message
bsr nextlin
rts
OtoAt moveq #11,d1 do not remove leading zeros
;move to remove leading zeros
OtoAtp move.l d0,d2
andi.l #$00000007,d2 get lsf
addi.l #$30,d2 ascii offset for num
OtoAct move.b d2,0(a1,d3.w) move to tempory buffer
subq #1,d3 point to next buffer place
lsr.l #3,d0 move next byte into LSBits (3)
subq #1,d1 decrememt counter, remove to delete leading
;zeros
smi err if negative, an error has occurred
bgt.s OtoAtp if greater convert next 3 bits
rts
;******************************************************************
;* BtoA *
;* Converts variable pointed to by VarPtr to *
;* a BIN ascii string for displaying. *
;******************************************************************
BtoA lea VarPtr,a0
move.l #12,d4 point to result
lea BuffT,a1 get address of tempory buffer
move.l #147,d3 point to end of buffer
GetB move.l 4(a0,d4),d0 get a varible
cmpi.b #12,d4 pointing to result
blt.s GetB0 no, no special treatment
cmpi.b #4,func is operation div
beq.s Bdiv yes, output in divid format
GetB0 cmpi #8,d4 remove if leading zeros are to be removed
bne.s GetB1 "
tst.l d0 "
bne.s GetB1 "
subq #4,d4 "
bsr Iequal "
bra.s GetB " "
GetB1 bsr BtoAt change variable to ascii in BIN base
tst.b err error in converstion
bne.s BtoAerr output error message
nextB subq #4,d4 point to next variable
bmi.s BTtoBB if negative all variables actioned
beq.s Boper d4 = 0, then output relavent operator
Bequal cmpi #4,d4 has total been actioned
bhi.s GetB higher, get high 32 bits of result
bsr Iequal d4 = 4, insert "=" sign
bra.s GetB get next variable
Boper bsr Ifunc branch to insert operator routine
bra GetB get next variable
BTtoBB lea BuffB,a0 a0 points to BIN output buffer
;jsr Rled0 remove leding zeros
jsr BTcopy do not remove leading zeros
rts
Bdiv move.l #9,d5 insert "remainder" into tempory buffer
lea rem,a2 a2 points to remainder
Bdiv1 move.b 0(a2,d5.w),d6 get a letter
move.b d6,0(a1,d3.w) put it into tempory buffer
subq #1,d3 point to next letter
dbf d5,Bdiv1 d5 = 0, then finished
Bdiv2 bsr BtoAt convet to ascii, BIN base
move.b #' ',0(a1,d3.w) if so add + to buffer
subq #1,d3
move.b #'+',0(a1,d3.w)
subq #1,d3
move.b #' ',0(a1,d3.w)
subq #1,d3
subq #4,d4 point to quotient
move.l 4(a0,d4.w),d0 get quotient
bsr BtoAt convert to ascii, BIN base
bra nextB get var2
BtoAerr lea HtoAI,a3 output error message
bsr nextlin
bra quit
BtoAt move.l #32,d1 do not remove leading zeros
;move to remove leading zeros
BtoAtp move.l d0,d2
andi.l #$00000001,d2 get lsbit
addi.l #$30,d2 ascii offset for num
BtoAct move.b d2,0(a1,d3.w) move to tempory buffer
subq #1,d3 point to next buffer place
lsr.l #1,d0 move next byte into LSBit
subq #1,d1 decrememt counter, remove to delete leading
;zeros
smi err if negative, an error has occurred
bgt.s BtoAtp if greater convert next bit
rts
;******************************************************************
;* DtoA *
;* Converts variable pointed to by VarPtr to *
;* a DEC ascii string for displaying. *
;******************************************************************
DtoA lea VarPtr,a0
move.l #12,d4 point to result
lea BuffT,a1 get address of tempory buffer
move.l #147,d3 point to end of buffer
GetD move.l 4(a0,d4.w),d0 get a variable
cmpi.b #12,d4 pointing to result
blt.s GetD0 no, no special treatment
cmpi.b #3,func is operation mult or div
beq Dtmul if equal, output in mult format
bgt Dtdiv if greater, output in div format
GetD0 tst.l d0 find sign of variable
bge.s GetD1
smi neg neg, set neg flag
neg.l d0 make number possible
GetD1 bsr HtoBCD change variable to ascii in DEC base
nextD subq #4,d4 point to next variable
bmi BTtoBD if negative all variables actioned
beq.s Doper d4 = 4, then insert operator
Dequal cmpi #4,d4 has total been actioned
bhi.s Getr no, go to save to buffer routine
bsr DequalI yes, insert "=" in tempory buffer
bra.s GetD get next variable
Getr bsr DtoAct move result from DecTemp to Tempory Buffer
subq #4,d4 point to next variable
bsr Iequal insert "=" into tempory buffer
bra GetD get next variable
Doper bsr DtoAct move var2 from DecTemp to Tempory Buffer
bsr Ifunc then insert operator
bra GetD get var1
DequalI bsr DtoAct move result from DecTemp to Tempory Buffer
bsr Iequal then insert equal sign
rts
BTtoBD bsr DtoAct move DecTemp to Buffer
lea BuffD,a0 point to DEC output buffer
jsr Rled0 remove leading zero's and move to output buffer
rts
; Dtmul uses two longwords to calculate decimal equivalent
Dtmul tst.l 0(a0,d4.w) is variable negative
bge.s Dtmul1 no, convert
smi neg yes, set neg flag
neg.l d0 neg low word
negx.l 0(a0,d4.w) neg (account for borrow if used for low word)
Dtmul1 bsr HtoBCD change variable to ascii in DEC base
subq #4,d4 point to next variable
move.l 4(a0,d4.w),d0 get high 32 bits
bsr BCDT miss out set up routine in HtoBCD
bra nextD move to tempory buffer and get next var2
; Dtdiv uses the lowword for remainder, high word for quotient
Dtdiv move.l #9,d5 insert "remainder" into tempory buffer
lea rem,a2 a2 points to remainder
Dtdiv1 move.b 0(a2,d5.w),d6 get a letter
move.b d6,0(a1,d3.w) put it into tempory buffer
subq #1,d3 point to next letter
dbf d5,Dtdiv1 d5 = 0, then finished
tst.l d0 is remainder negative
bpl.s Dtdiv2 no, convert
smi neg yes, set neg flag
neg.l d0 and make poitive
Dtdiv2 bsr HtoBCD change variable to ascii in DEC base
bsr DtoAct move to tempory buffer
tst.b neg was number negative
bpl.s Dtdiv3 no, add "+" to buffer
move.b #' ',0(a1,d3.w) yes, so add - to buffer
subq #1,d3
move.b #'-',0(a1,d3.w)
subq #1,d3
move.b #' ',0(a1,d3.w)
subq #1,d3
clr.b neg clear neg flag
bra.s Dtdiv4 convert quotient
Dtdiv3 move.b #' ',0(a1,d3.w) add + to buffer
subq #1,d3
move.b #'+',0(a1,d3.w)
subq #1,d3
move.b #' ',0(a1,d3.w)
subq #1,d3
Dtdiv4 subq #4,d4 point to next variable
move.l 4(a0,d4.w),d0 get quotient
tst.l d0 is it negative
smi.b neg set neg flag if negative
bpl.s Dtdiv5 no, convert
neg.l d0 yes, make it positive
Dtdiv5 bsr HtoBCD change variable to ascii in BIN base
bra nextD move to tempory buffer and get var2
; HtoBCD converts a HEX number to BCD
HtoBCD moveq #0,d5 clear d5
move.l #DecSize,d2 get size of DecTemp
lea DecTemp,a2 get address of DecTemp
HtoBCD2 move.b d5,0(a2,d2.w) clear a2 + d2
dbmi.w d2,HtoBCD2 all done, no do it again
lea DecCon1,a2 get address of DecCon1
BCDT moveq #8,d1 d1 holds the number of nibbles to do
BCDT0 move.l d0,d2 move variable to d2
andi.l #$0000000F,d2 get lsnibble
BCDT1 beq.s BCDT3 if zero get next significant nibble
lea DecCon0,a4 get address of DecCon0
andi #$EF,ccr clear extended flag in ccr
move.l a2,a3
adda.l d5,a3 calculate 16^x pointer
BCDT2 abcd -(a3),-(a4) add BCD from number pointed to by a3 to DecTemp
cmpa.l #DecTemp,a4 all bytes added
bne.s BCDT2 no, do next byte, elseget next significant nib
subq #1,d2 sub 1 from hex number
bra BCDT1 do again
BCDT3 lsr.l #4,d0 move next significant nibble into lsnibble
addi.l #12,d5 point to next 16^x (x = D5)
subq #1,d1 dec nibble count
bne.s BCDT0 if not zero do it again
BCDend rts
; DtoAct converts a BCD number to ASCII and moves it to a tempory buffer
DtoAct lea DecCon0,a4 point to end of DecTemp
DtoAct1 moveq #2,d5 d5 = nibble count
move.b -(a4),d0 move byte from DecTemp into d0
DtoAct2 move.b d0,d2
andi #$F,d2 get lsnibble
add.b #$30,d2 convert it to an ascii number
move.b d2,0(a1,d3.w) move to tempory buffer
subq #1,d3 point to next buffer position
lsr #4,d0 move nibble into lsnibble position
subq #1,d5 dec nibble count
bne.s DtoAct2 all nibbles done, no do next nibble
DtoAct3 cmpa.l #DecTemp-1,a4 else, all of DecTemp done?
bne.s DtoAct1 no, done next byte
tst.b neg was number negative
beq.s DtoActe no return
move.b #'-',0(a1,d3.w) else put negative in front of number
subq #1,d3 point to next buffer position
clr.b neg clear neg flag
DtoActe rts
DtoAerr lea HtoAI,a3 print error message
bsr nextlin
rts
***********************************************************
Iequal move.b #' ',0(a1,d3.w) add " = " to buffer
subq #1,d3
move.b #'=',0(a1,d3.w)
subq #1,d3
move.b #' ',0(a1,d3.w)
subq #1,d3
rts
Ifunc move.b #' ',0(a1,d3.w) add function to buffer
subq #1,d3
moveq #0,d5
move.b func,d5
subq #1,d5
lsl #2,d5 cal index for jump table
lea funcH,a3 get address of jump table
move.l 0(a3,d5.w),a3 get address of func routine
jsr (a3) insert correct function
move.b #' ',0(a1,d3.w)
subq #1,d3
rts
funcH dc.l Iadd,Isub,Imult,Idiv
Iadd move.b #'+',0(a1,d3.w) add + to buffer
subq #1,d3
rts
Isub move.b #'-',0(a1,d3.w) add - to buffer
subq #1,d3
rts
Imult move.b #'*',0(a1,d3.w) add * to buffer
subq #1,d3
rts
Idiv move.b #'/',0(a1,d3.w) add / to buffer
subq #1,d3
rts
;******************************************************************
;* Rmzero Kill leading zeros *
;* Inputs: a0 pointer to destination buffer *
;* a1 pointer to source *
;******************************************************************
Rled0 moveq #0,d0
moveq #0,d2
moveq #0,d1
addq #1,d3 compensate for last subq of d3
Rled01 move.b 0(a1,d3.w),d0 get character from buffer
addq #1,d3
cmpi.b #$30,d0 is it a zero
bne.s Rled02 check for other characters of interest
tst d1 has a character been output
beq.s Rled01 no, geet next character
bne.s BtoB2 yes, output "0"
Rled02 cmpi.b #$20,d0 is the character a space
beq.s BtoB yes, check if input betwwen spaces
cmpi #'-',d0 is it "-"?
beq.s BtoB3 move it to out put buffer
cmpi.b #LF,d0 end of tempory buffer
bne.s BtoB2 no, put character into buffer
tst d1 character between last space and Line Feed
bne Tnzero yes, put into buffer
move.b #'0',0(a0,d2.w) no, insert a "0" before Line Feed
addq #1,d2
moveq #LF,d0
Tnzero move.b d0,0(a0,d2.w) move to output buffer
addq #1,d2 inc output buffer pointer
move.b #0,0(a0,d2.w) put a NULL at end of output string
rts
BtoB tst d1 has a character been output
beq.s Val0 no, insert a "0"
moveq #3,d1 yes, d1 is used to count three characters
;move " ? " to output buffer. (? = +,-,*,/,=)
BtoB1 move.b d0,0(a0,d2.w) move character to output buffer
addq #1,d2 inc buffer pointer
subq #1,d1 dec character counter
beq.s BtoB1e all done, reset character output flag
move.b 0(a1,d3.w),d0 get character from temp buffer
addq #1,d3 inc buffer pointer
bra BtoB1 do again
BtoB1e moveq #0,d1 clear output flag
bra.s Rled01 get next character
BtoB2 move.b d0,0(a0,d2.w) move character to output buffer
addq #1,d2 inc buffer pointer
addq #1,d1 inc buffer pointer
bra Rled01 get next character
BtoB3 move.b d0,0(a0,d2.w) move character to output buffer
addq #1,d2 inc buffer pointer
bra Rled01 get next character
Val0 move.b #'0',0(a0,d2.w) move "0" to output buffer
addq #1,d2 inc buffer pointer
moveq #3,d1 move " ? " to output buffer. (? = +,-,*,/,=)
bra.s BtoB1
;******************************************************************
;* Copy from tempory buffer to output buffer *
;* Inputs: a0 pointer to destination buffer *
;* a1 pointer to source *
;******************************************************************
BTcopy moveq #0,d0
moveq #0,d2
moveq #0,d1
addq #1,d3 compensate for last subq of d3
BTcopy1 move.b 0(a1,d3.w),d0 get character from buffer
addq #1,d3 inc buffer pointer
cmpi.b #LF,d0 end of tempory buffer
beq.s BTcopy2 yes, end routine
move.b d0,0(a0,d2.w) move character to output buffer
addq #1,d2 inc buffer pointer
bra BTcopy1 get next character
BTcopy2 move.b d0,0(a0,d2.w) move character to output buffer
addq #1,d2 inc buffer pointer
move.b #0,0(a0,d2.w) put a NULL at end of output string
rts
;******************************************************************
;* *
;* Variables and Constants *
;* *
;******************************************************************
VarPtr ds.l 1
Var1 ds.l 1
Var2 ds.l 1
Total ds.l 2
func dc.b 0 ; 0,1,2,3,4 none,add,sub,Mult,Div
neg dc.b 0
err dc.b 0
BuffT ds.b 148
BuffTE dc.b $0a
BuffHS dc.b "HEX "
BuffH ds.b 52
BuffHe dc.b 0
BuffOS dc.b "OCT "
BuffO ds.b 64
BuffOE dc.b 0
BuffBS dc.b "BIN "
BuffB ds.b 148
BuffBE dc.b 0
BuffDS dc.b "DEC "
BuffD ds.b 55
BuffDE dc.b 0
rem dc.b " remainder"
even
DecTemp ds.w 6
DecCon0 dc.w $0000,$0000,$0000,$0000,$0000,$0001
DecCon1 dc.w $0000,$0000,$0000,$0000,$0000,$0016
DecCon2 dc.w $0000,$0000,$0000,$0000,$0000,$0256
DecCon3 dc.w $0000,$0000,$0000,$0000,$0000,$4096
DecCon4 dc.w $0000,$0000,$0000,$0000,$0006,$5536
DecCon5 dc.w $0000,$0000,$0000,$0000,$0104,$8576
DecCon6 dc.w $0000,$0000,$0000,$0000,$1677,$7216
DecCon7 dc.w $0000,$0000,$0000,$0002,$6843,$5456
DecCon8 dc.w $0000,$0000,$0000,$0042,$9496,$7296
DecCon9 dc.w $0000,$0000,$0000,$0687,$1947,$6736
DecConA dc.w $0000,$0000,$0001,$0995,$1162,$7776
DecConB dc.w $0000,$0000,$0017,$5921,$8604,$4416
DecConC dc.w $0000,$0000,$0281,$4749,$7671,$0656
DecConD dc.w $0000,$0000,$4503,$5996,$2737,$0496
DecConE dc.w $0000,$0007,$2057,$5940,$3792,$7936
DecConF dc.w $0000,$0115,$2921,$5046,$0694,$6976
DecEND dc.w $0000,$0000,$0000,$0000,$0000,$0000
DecSize equ (DecCon0-DecTemp)-1
even
ipadd dc.l 0
iplen dc.w 0
stdout dc.l 0
stdin dc.l 0
DosBase dc.l 0
DosName dc.b "dos.library",0
LF equ $0a
blank dc.b LF,0
HtoAI dc.b "You stuffed it up again",LF,0
oInfo dc.b "Error in operator",LF,0
hInfo dc.b "Error in hexadecimal number",LF,0
OInfo dc.b "Error in octal number",LF,0
BInfo dc.b "Error in binary number",LF,0
DInfo dc.b "Error in Decimal number",LF,0
adderrI dc.b "Overflow occured in addition, numbers are to large.",LF,0
suberrI dc.b "Overflow occured in subtraction, numbers are to large.",LF,0
dbyzI dc.b "Divid by zero",LF,0
Info dc.b "CAL <base> number operator <base> number <=> [return]",LF
dc.b " base: $ = HEX, @ = Octal, % = binary, none = decimal",LF
dc.b " number: HEX max 7FFFFFFF t0 80000000,",LF
dc.b " Decimal max +/-2147483647",LF
dc.b " operator: +,-,*,/",LF,LF,0
end